package com.fjwt.gz.service.impl;

import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.ApiCodeEnum;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.jwt.JWTPayload;
import com.fjwt.gz.core.model.ApiRes;
import com.fjwt.gz.core.model.DBsecurityConfig;
import com.fjwt.gz.core.model.security.GzUserDetails;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/***
 * 登录校验管理
 *
 * @author zx
 * @site https://pt.jdyd.xyz/
 * @date 2022/5/17 10:34
 */
@Slf4j
@Component
public class AuthManage {

    @Autowired private SysConfigService sysConfigService;

    /** 防穷举验证  **/
    public void loginErrValidate(String sysType, String username) {

        DBsecurityConfig dbSecurityConfig = sysConfigService.getDBSecurityConfig();
        if (dbSecurityConfig.getLoginErrorMaxLimit().getErrMax() == 0) {
            return;
        }

        String failPassCacheKey = CS.getCacheKeyLoginErr(sysType, username);
        String failCount = RedisUtil.getString(failPassCacheKey);
        if(StringUtils.isNotEmpty(failCount) && Integer.parseInt(failCount) >= dbSecurityConfig.getLoginErrorMaxLimit().getErrMax()){ //已经 临时锁定
            throw new BizException("密码输入错误次数超限，请稍后再试");
        }
    }

    /** 防穷举累加    还可尝试x次，失败将锁定x分账 **/
    public void loginErrCount(String sysType, String username) {

        DBsecurityConfig dbSecurityConfig = sysConfigService.getDBSecurityConfig();
        if (dbSecurityConfig.getLoginErrorMaxLimit().getErrMax() == 0) {
            throw new BizException("用户不存在");
        }

        String failPassCacheKey = CS.getCacheKeyLoginErr(sysType, username);

        //累加缓存统计数据
        long failCountL = RedisUtil.increment(failPassCacheKey, 1);
        RedisUtil.expire(failPassCacheKey, dbSecurityConfig.getLoginErrorMaxLimit().getLimitMinute(), TimeUnit.MINUTES); //缓存x分钟

        if(failCountL >= dbSecurityConfig.getLoginErrorMaxLimit().getErrMax()){ //超过xx次
            throw new BizException("密码输入错误次数超限，请稍后再试");
        }else{
            throw new BizException("用户名/密码错误，还可尝试" + ( dbSecurityConfig.getLoginErrorMaxLimit().getErrMax() - failCountL ) + "次，失败将锁定"
                    + dbSecurityConfig.getLoginErrorMaxLimit().getLimitMinute() + "分钟");
        }
    }


    /** 密码过期的过滤器，  返回： true: 已过期，请直接return,  false，正常请求  */
    public static boolean passwordExpiredFilter(GzUserDetails gzUserDetails, jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) throws IOException {

        // 系统不强制更改
        if(!SysConfigService.PWD_EXPIRED_MUST_RESET){
            return false;
        }

        // 如果密码认证 && 密码已过期
        if( JWTPayload.CREDENTIAL_AUTH_TYPE.PASSWORD.equals(gzUserDetails.getAuthType()) &&
                gzUserDetails.getSysUser().getPwdExpiredTime() != null && gzUserDetails.getSysUser().getPwdExpiredTime().compareTo(new Date()) <= 0) {

            String requestURI = request.getRequestURI();

            // 查询用户信息 修改密码，可操作
            if(requestURI.indexOf("/api/current/user") >= 0 || requestURI.indexOf("/api/current/modifyPwd") >= 0){
                return false;
            }

            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            response.getWriter().println(ApiRes.fail(ApiCodeEnum.SYS_USER_PWD_EXPIRED).toJSONString());
            response.getWriter().flush();
            return true;
        }

        return false;
    }

}
